from PyQt5.QtCore import QRect, QPointF
from PyQt5.QtGui import QBrush, QLinearGradient, QColor, QPen, QTextOption, QFontMetrics,QIcon
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication,QListWidget

import random

window_height = 10
begin_width_spacing = 20
begin_height_spacing = 16
icon_width = 40
icon_height = 40
text_width_spacing = 20  # 对话气泡文字两边间隔
text_height_spacing = 12  # 对话气泡文字上下间隔
triangle_width = 6  # 对话的三角形宽
triangle_height = 10  # 对话的三角形高
triangle_height_spacing = 10
text_min_width = 0
min_width = 0
text_max_width = 0
real_width = 0
text_height = 0

class MyWidget(QtWidgets.QWidget):
    def __init__(self, parent=None, data='hello，今天天气真好',type_mess = 0,head=1):
        super(MyWidget, self).__init__(parent)
        self.setObjectName('myWidget')
        self.user_chat_content = data
        self.left = type_mess
        self.head = head

    # 重写paintEvent 否则不能使用样式表定义外观
    def paintEvent(self, event):
        # 此函数用于初始化气泡边框的大小，决定于字数大小
        self.init_data()
        global text_min_width, min_width, text_max_width, real_width, text_height, window_height
        # 初始化QPainter对象，一支画笔
        painter = QtGui.QPainter(self)
        painter.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
        font = QtGui.QFont()
        font.setFamily("Decorative")
        font.setPointSize(12)
        painter.setFont(font)
        # 画头像
        if self.left:
            icon_rect = QRect(begin_width_spacing, begin_height_spacing, icon_width, icon_height)
        else:
            icon_rect = QRect(self.width()-begin_width_spacing-icon_width,begin_height_spacing, icon_width, icon_height)
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QtCore.Qt.gray))
        painter.drawPixmap(icon_rect, QtGui.QPixmap(f"head/{self.head}.png"))
        # 画框架
        if self.left:
            bubbleRect = QRect(begin_width_spacing + icon_width,
                               begin_height_spacing,
                               triangle_width + text_width_spacing + text_max_width + text_width_spacing,
                               text_height_spacing + text_height + text_height_spacing)
        else:
            bubbleRect = QRect(self.width()-begin_width_spacing-icon_width,
                               begin_height_spacing,
                               triangle_width + text_width_spacing + text_max_width + text_width_spacing,
                               text_height_spacing + text_height + text_height_spacing)

        print (f'bubbleRect:{bubbleRect}')
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QColor(180, 180, 180)))
        if self.left:
            painter.drawRoundedRect(bubbleRect.x() + triangle_width, bubbleRect.y(), bubbleRect.width() - triangle_width,
                                    bubbleRect.height(), 18, 18)
            linearGradient = QLinearGradient(QPointF(bubbleRect.x() + triangle_width + 1,
                                                     bubbleRect.y() + 1),
                                             QPointF(bubbleRect.x() + bubbleRect.width() - 1,
                                                     bubbleRect.y() + bubbleRect.height() - 1))
            print(f'linearGradient:{linearGradient}')
            linearGradient.setColorAt(0, QColor(255, 255, 255))
            linearGradient.setColorAt(0.25, QColor(255, 255, 255))
            linearGradient.setColorAt(0.5, QColor(255, 255, 255))
            linearGradient.setColorAt(0.75, QColor(255, 255, 255))
            linearGradient.setColorAt(1, QColor(255, 255, 255))

            painter.setBrush(linearGradient)
        else:
            painter.drawRoundedRect(bubbleRect.x()-triangle_width - text_width_spacing - text_max_width - text_width_spacing,bubbleRect.y(),  bubbleRect.width()-triangle_width,bubbleRect.height(), 18, 18)

            # painter.drawRoundedRect(bubbleRect.x()-triangle_width,
            #                         bubbleRect.y(),
            #                         -self.width()+bubbleRect.width() + triangle_width,
            #                         bubbleRect.height(), 18, 18)

            linearGradient = QLinearGradient(QPointF(bubbleRect.x() + triangle_width + 1,
                                                     bubbleRect.y() + 1),
                                             QPointF(bubbleRect.x() + bubbleRect.width() - 1,
                                                     bubbleRect.y() + bubbleRect.height() - 1))
            print (f'linearGradient:{linearGradient}')
            linearGradient.setColorAt(0, QColor(149, 236, 105))
            linearGradient.setColorAt(0.25, QColor(149, 236, 105))
            linearGradient.setColorAt(0.5, QColor(149, 236, 105))
            linearGradient.setColorAt(0.75, QColor(149, 236, 105))
            linearGradient.setColorAt(1, QColor(149, 236, 105))

            painter.setBrush(linearGradient)
        if self.left:
            painter.drawRoundedRect(bubbleRect.x() + triangle_width + 1, bubbleRect.y() + 1,
                                    bubbleRect.width() - triangle_width - 2, bubbleRect.height() - 2, 18, 18)
        else:
            print (f'kuan:{self.width()-bubbleRect.x()}')
            painter.drawRoundedRect(bubbleRect.x()-triangle_width - text_width_spacing - text_max_width - text_width_spacing + 1, bubbleRect.y() + 1,
                                    bubbleRect.width() - triangle_width - 2, bubbleRect.height() - 2, 18, 18)

        painter.setPen(QPen(QColor(244, 164, 96)))
        if self.left:
            painter.drawPolygon(QPointF(bubbleRect.x(),
                                        bubbleRect.y() + triangle_height_spacing - 4),
                                QPointF(bubbleRect.x() + triangle_width + 1,
                                        bubbleRect.y() + triangle_height_spacing),
                                QPointF(bubbleRect.x() + 6 + 1,
                                        bubbleRect.y() + 10 + 10))
        else:
            painter.drawPolygon(QPointF(bubbleRect.x(),
                                        bubbleRect.y() + triangle_height_spacing - 4),
                                QPointF(bubbleRect.x() - triangle_width - 1,
                                        bubbleRect.y() + triangle_height_spacing),
                                QPointF(bubbleRect.x() - 6 - 1,
                                        bubbleRect.y() + 10 + 10))

        painter.setPen(QPen(QColor(180, 180, 180)))
        print (f"QPointF:{QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4)}")
        if self.left:
            painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                             QPointF(bubbleRect.x() + 6, bubbleRect.y() + 10))
            painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                             QPointF(bubbleRect.x() + 6, bubbleRect.y() + 10 + 10))
        else:
            painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                             QPointF(bubbleRect.x() - 6, bubbleRect.y() + 10))
            painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                             QPointF(bubbleRect.x() - 6, bubbleRect.y() + 10 + 10))
        # 画文字
        penText = QPen()
        penText.setColor(QColor(56, 56, 56))
        painter.setPen(penText)

        if self.left:
            option = QTextOption(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
            option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
            painter.drawText(
                QRectF(bubbleRect.x() + triangle_width + text_width_spacing, bubbleRect.y() + text_height_spacing,
                       text_max_width, text_height), self.user_chat_content, option)
        else:
            option = QTextOption(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
            option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
            painter.drawText(
                QRectF(bubbleRect.x()-triangle_width - text_width_spacing - text_max_width, bubbleRect.y() + text_height_spacing,
                       text_max_width, text_height), self.user_chat_content, option)

        print (QRectF(bubbleRect.x() + triangle_width + text_width_spacing, bubbleRect.y() + text_height_spacing,
                   text_max_width, text_height))
        #self.width()-bubbleRect.x()-triangle_width+10

    def init_data(self):
        font = QtGui.QFont()
        font.setFamily("Decorative")
        font.setPointSize(12)
        metrics = QFontMetrics(font)
        global text_min_width, min_width, text_max_width, real_width, text_height, window_height
        print(f'text_max_width:{text_max_width}')
        print (f'begin_height_spacing:{metrics.width("A") * 2 + begin_height_spacing * 1.5},text_width_spacing:{text_width_spacing}')
        if metrics.width("A") * 2 + begin_height_spacing * 1.5 < text_width_spacing:
            text_min_width = begin_height_spacing * 1.5 - text_width_spacing
        else:
            text_min_width = 0
            min_width = begin_width_spacing + icon_width + triangle_width + text_width_spacing + text_width_spacing + icon_width + begin_width_spacing
        # print (f'self.width:{self.width}')
        if self.width() > min_width + text_min_width:
            self.setMinimumWidth(min_width + text_min_width)
            text_max_width = self.width() - min_width
            real_width = metrics.width(self.user_chat_content)
        # print(f'text_height_spacing:{text_height_spacing}')
        if real_width < text_max_width:
            print ('确实时大于')
            text_max_width = real_width
            if text_height_spacing + metrics.height() + text_height_spacing > triangle_height_spacing + triangle_height + triangle_height_spacing:
                text_height = metrics.height()
            else:
                text_height = triangle_height_spacing + triangle_height + triangle_height_spacing
        else:
            flag = QtCore.Qt.TextWordWrap
            textRect = QRect(0, 0, text_max_width, 0)
            # 自动换行
            textRect = metrics.boundingRect(textRect, flag, self.user_chat_content)
            print (f'textRect:{textRect}')
            text_height = textRect.height()
            text_max_width = textRect.width()

class Mainwindow(QtWidgets.QWidget):
    def __init__(self):
        super(Mainwindow, self).__init__()
        self.resize(500, 400)

        user_say_1 = MyWidget(data='你好，'+f"我是伞兵{random.choice(range(50))}号",type_mess=1,head=1)
        user_ans_1 = MyWidget(data='伞兵你好',type_mess=0,head=2)
        user_say_2 = MyWidget(data='我迷路了，四周都是荒漠，现在快要脱水了，我该怎么办?', type_mess=1,head=1)
        user_ans_2 = MyWidget(data='多喝点热水，好好照顾自己!', type_mess=0,head=2)
        user_say_3 = MyWidget(data='栓Q', type_mess=1,head=1)

        self.chat = QListWidget(self)
        # 添加常规item
        # self.chat.addItem('你好')

        # 添加自定义widget
        self.addwidget_list(user_say_1)
        self.addwidget_list(user_ans_1)
        self.addwidget_list(user_say_2)
        self.addwidget_list(user_ans_2)
        self.addwidget_list(user_say_3)


        layout_0 = QtWidgets.QHBoxLayout()
        layout_0.addWidget(self.chat)

        self.setLayout(layout_0)
        self.show()

    def addwidget_list(self,user_say):
        dataView_item = QtWidgets.QListWidgetItem()
        dataView_item.setSizeHint(QSize(100, 100))
        self.chat.addItem(dataView_item)
        self.chat.setItemWidget(dataView_item, user_say)

if __name__ == "__main__":
    from PyQt5.QtCore import *
    import sys

    if hasattr(Qt, 'AA_EnableHighDpiScaling'):
        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
    if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
        QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)

    app = QApplication(sys.argv)
    # app.setWindowIcon(QIcon('google_translate.ico'))
    form = Mainwindow()
    # form.show()
    sys.exit(app.exec_())